package com.wobito.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wobito.common.constants.BusinessException;
import com.wobito.common.constants.ErrorCode;
import com.wobito.common.constants.SysConstants;
import com.wobito.common.utils.DateUtils;
import com.wobito.common.utils.StringUtils;
import com.wobito.mapper.BookMapper;
import com.wobito.mapper.BorrowMapper;
import com.wobito.mapper.BorrowReturnLogMapper;
import com.wobito.pojo.bean.*;
import com.wobito.pojo.dto.api.GetBookByCabinetDTO;
import com.wobito.pojo.dto.book.BookByLatIdDTO;
import com.wobito.pojo.dto.book.BookByQueryNameDTO;
import com.wobito.pojo.dto.book.BookDTO;
import com.wobito.pojo.enums.BorrowStatusEnum;
import com.wobito.pojo.vo.book.AddBookVO;
import com.wobito.pojo.vo.book.BookVO;
import com.wobito.pojo.vo.book.UpdateBookVO;
import com.wobito.service.BookService;
import com.wobito.service.IConfigTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author Wangbaba
 * @Date 2024/7/1 10:14
 * @Version 1.0
 */
@Service
public class BookServiceImpl extends ServiceImpl<BookMapper, Book>
        implements BookService {

    @Autowired
    private IConfigTypeService configTypeService;
    @Autowired
    private BookMapper bookMapper;
    @Autowired
    private BorrowMapper borrowMapper;
    @Autowired
    private BorrowReturnLogMapper borrowReturnLogMapper;

    /**
     * 获取系统默认配置期限
     *
     * @return
     */
    private Integer getDefaultTime() {
        ConfigType configType = configTypeService.getOne(new LambdaQueryWrapper<ConfigType>().eq(ConfigType::getConfigKey, "borrow:book:time"));
        return StringUtils.isEmpty(configType.getConfigValue()) ? 7 : Integer.valueOf(configType.getConfigValue());
    }

    /**
     * 根据借阅日志解析出归还状态
     *
     * @param borrow
     * @return
     */
    private Integer getStateLog(Borrow borrow) {
        //如果没有续借日期并且当前时间小于应还时间 -顺期
        if (borrow.getRenewDay() == null && borrow.getRenewTime() == null) {
            if (DateUtils.isDateBefore(DateUtils.getNowDate(), borrow.getDueTime())) {
                return SysConstants.ORDINARY_RETURN_TYPE;
            } else {
                return SysConstants.OVDRDUE_RETURN_TYPE;
            }
        } else {
            //如有续借应该重新计算
            if (DateUtils.isDateBefore(DateUtils.getNowDate(), borrow.getRenewTime())) {
                return SysConstants.RENEWAL_RETURN_TYPE;
            } else {
                return SysConstants.OVDRDUE_RETURN_TYPE;
            }
        }
    }

    @Override
    public List<BookDTO> selectBookList(BookVO bookVO) {
        return bookMapper.selectBookList(bookVO);
    }

    @Override
    public List<BookByLatIdDTO> selectFilesByLatId(Long latId) {
        List<BookByLatIdDTO> bookByLatIdDTOS = new ArrayList<>();
        List<Book> books = bookMapper.selectList(new LambdaQueryWrapper<Book>().eq(Book::getLatId, latId).eq(Book::getState, SysConstants.STATE_FILE_ZK));
        if (CollectionUtil.isNotEmpty(books)) {
            bookByLatIdDTOS = books.stream().map(b -> {
                BookByLatIdDTO book = BeanUtil.copyProperties(b, BookByLatIdDTO.class);
                return book;
            }).collect(Collectors.toList());
        }
        return bookByLatIdDTOS;
    }

    @Override
    public List<BookByQueryNameDTO> selectFileByQueryName(String queryName) {
        return bookMapper.selectFileByQueryName(queryName);
    }

    @Override
    public Book selectBookByRFID(String rfid) {
        Book book = bookMapper.selectOne(new LambdaQueryWrapper<Book>().eq(Book::getRfid, rfid));
        if (ObjectUtil.isNull(book)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "未查询到书籍信息(RFID):" + rfid);
        }
        return book;
    }

    @Override
    public List<GetBookByCabinetDTO> selectBookByCabinet(Long cabinetId) {
        return bookMapper.selectBookByCabinet(cabinetId);
    }

    @Override
    public long selectBookNumByCabinet(Long cabinetId, Integer state) {
        return bookMapper.selectBookNumByCabinet(cabinetId, state);
    }

    @Override
    public int insertBook(AddBookVO addBookVO) {
        Book book = BeanUtil.copyProperties(addBookVO, Book.class);
        return bookMapper.insert(book);
    }

    @Override
    public int updateBook(UpdateBookVO updateBookVO) {
        Book book = BeanUtil.copyProperties(updateBookVO, Book.class);
        book.setUpdateTime(DateUtils.getNowDate());
        return bookMapper.updateById(book);
    }

    @Override
    public int updateQueryNumById(List<Long> ids) {
        return bookMapper.updateQueryNumById(ids);
    }

    @Override
    public int inventoryBooks(List<String> rfids, Long latId, Long personId) {
        for (String rfid : rfids) {
            Book book = bookMapper.selectOne(new LambdaQueryWrapper<Book>().eq(Book::getRfid, rfid).eq(Book::getIsDeleted, SysConstants.STATE_SYSTEM_ZC));
            if (ObjectUtil.isEmpty(book)) {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "未查询到书籍信息(RFID):" + rfid);
            }
            if (!book.getLatId().equals(latId)) {
                book.setLatId(latId);
            }
            //如果书籍借出却在柜了就盘存
            if (!book.getState().equals(SysConstants.STATE_FILE_ZK)) {
                Borrow borrow = borrowMapper.selectOne(new LambdaQueryWrapper<Borrow>().eq(Borrow::getBookId, book.getId()));
                if (ObjectUtil.isNotNull(borrow)) {
                    borrowMapper.deleteById(borrow.getId());
                }
                borrowReturnLogMapper.insertReturnLog(new ReturnLog(personId, book.getId(), SysConstants.MANAGE_RETURN_TYPE, DateUtils.getNowDate()));
            }
            book.setState(SysConstants.STATE_FILE_ZK);
            bookMapper.updateById(book);
        }
        return 1;
    }

    @Override
    public int outBoundBooks(List<String> rfids, Long latId, Long personId) {
        List<Book> books = bookMapper.selectList(new LambdaQueryWrapper<Book>().in(Book::getRfid, rfids));
        if (CollectionUtil.isEmpty(books)) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "RFID识别错误");
        }
        //借阅时一次性出库不会太大直接循环
        for (Book book : books) {
            book.setState(SysConstants.STATE_FILE_QC);
            book.setBorrowNum(book.getBorrowNum() + 1);
            book.setBorrowTime(DateUtils.getNowDate());
            book.setUpdateTime(DateUtils.getNowDate());
            bookMapper.updateById(book);
            //创建借阅信息
            Borrow borrow = new Borrow(personId, book.getId(), BorrowStatusEnum.BORROW.getCode());
            borrow.setStartTime(DateUtils.getNowDate());
            borrow.setDueTime(DateUtils.increaseDate(borrow.getStartTime(), getDefaultTime()));
            borrowMapper.insert(borrow);
            //记录借阅日志
            borrowReturnLogMapper.insertBorrowLog(new BorrowLog(personId, book.getId(), DateUtils.getNowDate()));
        }
        return 1;
    }

    @Override
    public int inBoundBooks(List<String> rfids, Long latId, Long personId) {
        List<Book> books = bookMapper.selectList(new LambdaQueryWrapper<Book>().in(Book::getRfid, rfids));
        if (CollectionUtil.isEmpty(books)) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "RFID识别错误");
        }
        //借阅时一次性出库不会太大直接循环
        for (Book book : books) {
            book.setState(SysConstants.STATE_FILE_ZK);
            book.setUpdateTime(DateUtils.getNowDate());
            bookMapper.updateById(book);
            Borrow borrow = borrowMapper.selectOne(new LambdaQueryWrapper<Borrow>().eq(Borrow::getBookId, book.getId()).eq(Borrow::getPersonId, personId));
            //记录归还日志
            borrowReturnLogMapper.insertReturnLog(new ReturnLog(personId, book.getId(), getStateLog(borrow), DateUtils.getNowDate()));
            //删除借阅信息
            borrowMapper.deleteById(borrow.getId());
        }
        return 1;
    }

}
